﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace GraphicsEditor
{
    class Filters
    {
        public static Bitmap grayScale(Bitmap toChange)
        {
            Bitmap changedBitmap = new Bitmap(toChange);
            BitmapData bmData = changedBitmap.LockBits(new Rectangle(0, 0, changedBitmap.Width, changedBitmap.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);//PixelFormat.Format24bppRgb);
            int stride = bmData.Stride;
            IntPtr Scan0 = bmData.Scan0;
            // haha, even C# considers pointers unsafe!
            // The only way to access the pixel data is through pointers
            unsafe
            {
                byte* pixel = (byte*)(void*)Scan0;

                int nOffset = stride - changedBitmap.Width * 4;

                byte alpha, red, green, blue;

                for (int y = 0; y < changedBitmap.Height; ++y)
                {
                    for (int x = 0; x < changedBitmap.Width; ++x)
                    {
                        blue = pixel[0];
                        green = pixel[1];
                        red = pixel[2];
                        alpha = pixel[3];
                        //To convert any color to a grayscale representation of its luminance, first one must obtain the values of its red, 
                        //green, and blue (RGB) primaries in linear intensity encoding, by gamma expansion. Then, add together 
                        //30% of the red value, 59% of the green value, and 11% of the blue value (from wikipedia)
                        pixel[0] = pixel[1] = pixel[2] = (byte)(.30 * red
                            + .59 * green
                            + .11 * blue);
                        pixel += 4;
                    }
                    pixel += nOffset;
                }
            }
            changedBitmap.UnlockBits(bmData);
            return changedBitmap;
        }

        public static Bitmap invert(Bitmap toChange)
        {
            Bitmap changedBitmap = new Bitmap(toChange);
            BitmapData bmData = changedBitmap.LockBits(new Rectangle(0, 0, changedBitmap.Width, changedBitmap.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);//PixelFormat.Format24bppRgb);
            int stride = bmData.Stride;
            IntPtr Scan0 = bmData.Scan0;
            // haha, even C# considers pointers unsafe!
            // The only way to access the pixel data is through pointers
            unsafe
            {
                byte* pixel = (byte*)(void*)Scan0;

                int nOffset = stride - changedBitmap.Width * 4;

                for (int y = 0; y < changedBitmap.Height; ++y)
                {
                    for (int x = 0; x < changedBitmap.Width; ++x)
                    {
                        pixel[0] = (byte)(255 - pixel[0]);
                        pixel[1] = (byte)(255 - pixel[1]);
                        pixel[2] = (byte)(255 - pixel[2]);
                        pixel += 4;
                    }
                    pixel += nOffset;
                }
            }
            changedBitmap.UnlockBits(bmData);
            return changedBitmap;
        }
        public static Bitmap makeBlank(Bitmap toChange)
        {
            Bitmap changedBitmap = new Bitmap(toChange);
            BitmapData bmData = changedBitmap.LockBits(new Rectangle(0, 0, changedBitmap.Width, changedBitmap.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);//PixelFormat.Format24bppRgb);
            int stride = bmData.Stride;
            IntPtr Scan0 = bmData.Scan0;
            // haha, even C# considers pointers unsafe!
            // The only way to access the pixel data is through pointers
            unsafe
            {
                byte* pixel = (byte*)(void*)Scan0;

                int nOffset = stride - changedBitmap.Width * 4;

                for (int y = 0; y < changedBitmap.Height; ++y)
                {
                    for (int x = 0; x < changedBitmap.Width; ++x)
                    {
                        pixel[0] = (byte)255;
                        pixel[1] = (byte)255;
                        pixel[2] = (byte)255;
                        pixel[3] = (byte)255;
                        pixel += 4;
                    }
                    pixel += nOffset;
                }
            }
            changedBitmap.UnlockBits(bmData);
            return changedBitmap;
        }
        public static Bitmap winterize(Bitmap image)
        {

            try
            {
                //create a Bitmap the size of the image provided 
                Bitmap bmp = new Bitmap(image.Width, image.Height);

                //create a graphics object from the image 
                using (Graphics gfx = Graphics.FromImage(bmp))
                {
                    float[][] matrixItems = {
                        new float[] {0.2f, 0, 0, 0, 0},
                        new float[] {0, 0.8f, 1, 0, 0},
                        new float[] {0, 0, 1, 0, 0},
                        new float[] {0, 0, 0, 1, 0}, 
                        new float[] {0, 0, 0, 0, 1}};

                    ColorMatrix matrix = new ColorMatrix(matrixItems);
                    //set the opacity 
                    //matrix.Matrix33 = opacity;

                    //create image attributes 
                    ImageAttributes attributes = new ImageAttributes();

                    //set the color(opacity) of the image 
                    attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

                    //now draw the image 
                    gfx.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
                }
                return bmp;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return null;
            }
        }
    }
}
